﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace _06.delegate_action_func
{
    //delegate就是函数指针，最大用处就是用作参数类型
    //Action是预定义的无返回的委托类型: Action,Action<0~16>
    //Func是预定义的有返回的委托类型: Func<ResultType>, Func<0~16 InType, ResultType>
    class Program
    {
        static void Main(string[] args)
        {
            {//无参无返回
                Action a = () => Console.WriteLine("hehe");
                a.Invoke(); //
                a();

                a.BeginInvoke(null, null);//异步执行 - 见35行！
            }
            {//有参无返回,最多16个参数及类型
                Action<int> a = (i) => Console.WriteLine(i.ToString());
                a.Invoke(3);
                a(2);
            }

            {//Func 无参有返回
                Func<int> func = () => 1;
                int r = func();
                Console.WriteLine(r);

                var re = func.BeginInvoke(null, null);//异步执行！
                ///////////第一种获取异步完成的结果
                while (!re.IsCompleted) //等待异步执行完成
                {
                    Thread.Sleep(100);
                }
                int result = func.EndInvoke(re);//获取执行结果
                Console.WriteLine("异步执行的结果：" + result);

                ///////////第二种获取异步完成的结果
                re.AsyncWaitHandle.WaitOne();//有重载，可以设定等待的时间
                int result2 = func.EndInvoke(re);//获取执行结果

                ///////////第三种获取异步完成的结果：使用回调
                ///
            }
            {//Func 有参有返回
                Func<string, int> func = (s) => Convert.ToInt32(s);
                int r = func("1111111");
                Console.WriteLine(r);
            }

            ///////////////////////////////////////
            ///多播，一个委托指向多个方法引用 - 添加的顺序就是调用的顺序。如果有返回值，只能得到最后一个返回值！如果有异常，整个调用都会停止！
            {
                Action a = () => Console.WriteLine(111);
                a += () => Console.WriteLine(222); //+=, -=
                a += () => Console.WriteLine(333); //

                a();

                Delegate[] dd = a.GetInvocationList(); //可以手动一一调用，传递参数以及获取返回值
                foreach (var d in dd)
                {
                    d.DynamicInvoke(null);//如果有参数，在这里传入，可变
                }
            }

            Console.ReadKey();
        }
    }
}
